#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <unordered_map>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>
#include <errno.h>
#include <iomanip>
#include <csignal>
#include "client_manage.h"
#include "thread_safe_queue.h"
#include "parse_info.h"

ServerState g_state;

const int CONNECTION_TIMEOUT = 15;
ClientManager client_manager;

std::unordered_map<ConfigKey, int> init_config() {
    return {
        {ConfigKey::PORT, 8080},
        {ConfigKey::BUFFER_SIZE, 1024},
        {ConfigKey::BACKLOG, 5},
        {ConfigKey::MAX_EVENTS, 64},
        {ConfigKey::EPOLL_TIMEOUT, 1000}, // 1秒超时
        {ConfigKey::THREAD_POOL_SIZE, 4},
        {ConfigKey::HEARTBEAT_INTERVAL, 2}, // 心跳检测间隔(秒)
        {ConfigKey::CONNECTION_TIMEOUT, 15} // 连接超时时间(秒)
    };
}

// 心跳检测线程
void heartbeat_thread(int heartbeat_interval) {
    while (g_state.running) {
        std::this_thread::sleep_for(std::chrono::seconds(heartbeat_interval));
        auto now              = std::chrono::steady_clock::now();
        auto inactive_clients = client_manager.remove_inactive_clients(now);
        for (const auto &client_fd : inactive_clients) {
            std::cout << "客户端FD " << client_fd << " 心跳超时，断开连接" << std::endl;
            close(client_fd);
        }
    }
    std::cout << "heartbeat thread exit" << std::endl;
}

int set_nonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1) {
        return -1;
    }
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

void send_data(int fd, const std::vector<char> &data) {
    // 处理回声任务
    ssize_t bytes_sent = send(fd, data.data(), data.size(), 0);
    if (bytes_sent == -1) {
        std::cerr << "发送数据到FD " << fd << " 失败: " << strerror(errno) << std::endl;
        close(fd);
        client_manager.remove_client(fd);

    } else {
        std::cout << "已回声 " << bytes_sent << " 字节到FD " << fd << std::endl;
    }
}

epoll_event init_epoll_event() {
    // 创建epoll实例
    g_state.epoll_fd = epoll_create1(0);
    if (g_state.epoll_fd == -1) {
        std::cerr << "创建epoll实例失败: " << strerror(errno) << std::endl;
        close(g_state.server_fd);
        exit(1);
    }

    // 添加服务器套接字到epoll
    epoll_event event;
    event.data.fd = g_state.server_fd;
    event.events  = EPOLLIN | EPOLLET; // 边缘触发模式
    if (epoll_ctl(g_state.epoll_fd, EPOLL_CTL_ADD, g_state.server_fd, &event) == -1) {
        std::cerr << "添加服务器套接字到epoll失败: " << strerror(errno) << std::endl;
        close(g_state.server_fd);
        close(g_state.epoll_fd);
        exit(1);
    }
    return event;
}

void init_server_socket(std::unordered_map<ConfigKey, int> &config) {
    // 创建服务器套接字
    g_state.server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (g_state.server_fd == -1) {
        std::cerr << "创建套接字失败: " << strerror(errno) << std::endl;
        exit(1);
    }

    // 设置套接字选项
    int opt = 1;
    if (setsockopt(g_state.server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
        std::cerr << "设置套接字选项失败: " << strerror(errno) << std::endl;
        close(g_state.server_fd);
        exit(1);
    }

    // 绑定地址和端口
    sockaddr_in server_addr;
    server_addr.sin_family      = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port        = htons(config[ConfigKey::PORT]);

    if (bind(g_state.server_fd, (sockaddr *)&server_addr, sizeof(server_addr))) {
        std::cerr << "绑定地址失败: " << strerror(errno) << std::endl;
        close(g_state.server_fd);
        exit(1);
    }

    // 设置为非阻塞模式
    if (set_nonblocking(g_state.server_fd) == -1) {
        std::cerr << "设置非阻塞模式失败: " << strerror(errno) << std::endl;
        close(g_state.server_fd);
        exit(1);
    }

    // 开始监听
    if (listen(g_state.server_fd, config[ConfigKey::BACKLOG])) {
        std::cerr << "监听失败: " << strerror(errno) << std::endl;
        close(g_state.server_fd);
        exit(1);
    }

    std::cout << "服务器启动，正在监听端口 " << config[ConfigKey::PORT] << "..." << std::endl;
}

extern ThreadSafeQueue<Task> task_queue;
// 信号处理函数
void signal_handler(int signal) {
    if (signal == SIGINT) {
        std::cout << "ctrl+c caught, exiting..." << std::endl;
        g_state.running = false;
    }
}

int main(int argc, char *argv[]) {
    std::unordered_map<ConfigKey, int> config = init_config();
    // 解析命令行参数

    parse_command_line(argc, argv, config);

    show_config_info(config);
    // 设置 Ctrl+C 的信号处理器
    signal(SIGINT, signal_handler);

    init_thread_pool(config[ConfigKey::THREAD_POOL_SIZE]);
    client_manager.set_connection_timeout(config[ConfigKey::CONNECTION_TIMEOUT]);

    // 初始化服务器套接字和epoll事件
    init_server_socket(config);
    epoll_event event = init_epoll_event();

    // 启动心跳检测线程
    g_state.hb_thread = std::thread(heartbeat_thread, config[ConfigKey::HEARTBEAT_INTERVAL]);

    // 事件缓冲区
    epoll_event events[config[ConfigKey::MAX_EVENTS]];
    char buffer[config[ConfigKey::BUFFER_SIZE]];

    while (g_state.running) {
        // 等待事件
        int num_events = epoll_wait(g_state.epoll_fd, events, config[ConfigKey::MAX_EVENTS],
                                    config[ConfigKey::EPOLL_TIMEOUT]);
        if (num_events == -1) {
            if (errno == EINTR) {
                continue; // 被信号打断，重新进入等待
            } else {
                perror("epoll_wait");
                break;
            }
        }

        for (int i = 0; i < num_events; ++i) {
            // 处理新连接
            if (events[i].data.fd == g_state.server_fd) {
                sockaddr_in client_addr;
                socklen_t client_len = sizeof(client_addr);
                int client_fd;

                // 边缘触发模式下需要接受所有连接
                while ((client_fd = accept(g_state.server_fd, (sockaddr *)&client_addr,
                                           &client_len)) != -1) {
                    // 设置为非阻塞模式
                    if (set_nonblocking(client_fd) == -1) {
                        std::cerr << "设置客户端非阻塞模式失败: " << strerror(errno) << std::endl;
                        close(client_fd);
                        continue;
                    }

                    char client_ip[INET_ADDRSTRLEN];
                    inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
                    std::cout << "新客户端连接: " << client_ip << ":" << ntohs(client_addr.sin_port)
                              << " (FD: " << client_fd << ")" << std::endl;

                    // 添加客户端到epoll
                    event.data.fd = client_fd;
                    event.events = EPOLLIN | EPOLLET | EPOLLRDHUP; // 监听读事件和挂断事件
                    if (epoll_ctl(g_state.epoll_fd, EPOLL_CTL_ADD, client_fd, &event) == -1) {
                        std::cerr << "添加客户端到epoll失败: " << strerror(errno) << std::endl;
                        close(client_fd);
                        continue;
                    }
                    client_manager.add_client(client_fd);
                }

                if (errno != EAGAIN && errno != EWOULDBLOCK) {
                    std::cerr << "接受连接错误: " << strerror(errno) << std::endl;
                }
            }
            // 处理客户端挂断
            else if (events[i].events & EPOLLRDHUP) {
                int client_fd = events[i].data.fd;
                std::cout << "客户端FD " << client_fd << " 断开连接" << std::endl;
                close(client_fd);
                client_manager.remove_client(client_fd);
            }
            // 处理可读事件
            else if (events[i].events & EPOLLIN) {
                int client_fd = events[i].data.fd;
                ssize_t bytes_read;

                // 边缘触发模式下需要读取所有数据
                while ((bytes_read = recv(client_fd, buffer, config[ConfigKey::BUFFER_SIZE], 0)) >
                       0) {
                    buffer[bytes_read] = '\0';
                    std::cout << "从FD " << client_fd << " 接收到 " << bytes_read
                              << " 字节: " << buffer;
                    client_manager.update_client_activity(client_fd);
                    // 创建任务并加入线程池队列
                    Task task;
                    task.fd = client_fd;
                    task.data.assign(buffer, buffer + bytes_read);
                    add_task(task);
                }

                if (bytes_read == 0) {
                    // 客户端正常关闭
                    client_manager.remove_client(client_fd);
                    std::cout << "客户端FD " << client_fd << " 断开连接" << std::endl;
                    close(client_fd);

                } else if (bytes_read == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
                    // 读取错误
                    client_manager.remove_client(client_fd);
                    std::cerr << "从FD " << client_fd << " 接收数据错误: " << strerror(errno)
                              << std::endl;
                    close(client_fd);
                }
            }
        }
    }
    std::cout << "main exit" << std::endl;

    g_state.hb_thread.join();

    // 关闭所有客户端连接
    {
        auto all_clients = client_manager.get_all_clients();
        for (const auto &client_fd : all_clients) {
            close(client_fd);
        }
    }

    close(g_state.server_fd);
    close(g_state.epoll_fd);
    task_queue.stop(); // 停止任务队列
    destroy_thread_pool();
    return 0;
}